﻿/*
* Copyright (C) Microsoft. All rights reserved.  
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not 
* use this file except in compliance with the License.  You may obtain a copy 
* of the License at http://www.apache.org/licenses/LICENSE-2.0  
* 
* THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
* WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
* MERCHANTABLITY OR NON-INFRINGEMENT. 
*
* See the Apache License, Version 2.0 for specific language governing 
* permissions and limitations under the License.
*
*/
//
// page.xaml.cpp
// Implementation of the page class
//

#include "pch.h"
#include "page.xaml.h"
#include <journal/app/constants.h>
#include <journal/common/util.h>

using namespace journal;

using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Controls::Primitives;
using namespace Windows::UI::Xaml::Data;
using namespace Windows::UI::Xaml::Input;
using namespace Windows::UI::Xaml::Media;
using namespace Windows::UI::Xaml::Navigation;
using namespace Windows::ApplicationModel::DataTransfer;
using namespace Windows::UI::ApplicationSettings;
using namespace Windows::UI::Popups;

namespace a = baja::app;

page::page()
{
    InitializeComponent();

    PointerVisualizationSettings^ settings = PointerVisualizationSettings::GetForCurrentView();
    settings->IsBarrelButtonFeedbackEnabled = false;
    settings->IsContactFeedbackEnabled = false;


    _AppBar->Closed += ref new Windows::Foundation::EventHandler<Platform::Object^>(
        this, 
        &page::onAppBarClosed
        );

    _AppBar->Opened += ref new Windows::Foundation::EventHandler<Platform::Object^>(
        this, 
        &page::onAppBarOpened
        );

    _settingsToken = SettingsPane::GetForCurrentView()->CommandsRequested += 
        ref new TypedEventHandler<SettingsPane^, SettingsPaneCommandsRequestedEventArgs^>(
            this, 
            &page::onCommandsRequested
            );

    _uiService = std::dynamic_pointer_cast<a::iui_service>(std::make_shared<ui_service>(this));
}

void page::onLaunched()
{
    // observe settings service
    if (_settingsObserver == nullptr)
    {
        _settingsObserver = std::dynamic_pointer_cast<isettings_service_observer>(std::make_shared<settings_observer>(this));
        constants::settings()->addObserver(_settingsObserver);
    }

    this->updateBackgroundColorSetting();
    this->updateTouchInputModeIcon();
}

void page::onAppBarOpened(Platform::Object^ sender, Platform::Object^ args)
{
    this->refreshAppBar();

    std::shared_ptr<ui_service> serviceImpl = std::dynamic_pointer_cast<ui_service>(_uiService);
    serviceImpl->raiseAppBarVisibilityChange(true);
}

void page::refreshAppBar()
{
    // enable/disable paste image button
    DataPackageView^ packageView = Windows::ApplicationModel::DataTransfer::Clipboard::GetContent();
    if (packageView->Contains(Windows::ApplicationModel::DataTransfer::StandardDataFormats::Bitmap))
    {
        _Paste->IsEnabled = true;
        PasteImage->Source = PasteImageEnabled->Source;
    }
    else
    {
        _Paste->IsEnabled = false;
        PasteImage->Source = PasteImageDisabled->Source;
    }

    this->updateColorIcon();
    this->updateThicknessIcon();
    this->updateToolIcon();
    this->updateTouchInputModeIcon();
    this->updatePaperTypeIcon();
    this->updateZoomIcon();
    this->updateCameraIcon();

    // hide-show some of the buttons depending on the resolution
    Windows::UI::Xaml::Visibility visibility = Windows::UI::Xaml::Visibility::Visible;
    if (constants::shellService()->windowSize().x < 768)
    {
        visibility = Windows::UI::Xaml::Visibility::Collapsed;
    }

    ZoomLevel->Visibility = visibility;	
    Camera->Visibility = visibility;	
    _Paste->Visibility = visibility;	
    PaperType->Visibility = visibility;
    _Add->Visibility = visibility;
}

void page::onZoomLevelChanged()
{
    this->updateZoomIcon();
}

void page::onStackStateChanged()
{
    this->updateZoomIcon();
}

void page::updateZoomIcon()
{
    switch (constants::general::zoomLevel())
    {
        case view::layout_id::full: 
            ZoomLevelImage->Source = ZoomFullPageImage->Source;
            ZoomExpandStack->IsEnabled = true;
            ZoomExpandStackImage->Source = ZoomExpandStackImageEnabled->Source;
            break;

        case view::layout_id::fitToWidth: 
            ZoomLevelImage->Source = ZoomFitToWidthImage->Source;
            ZoomExpandStack->IsEnabled = true;
            ZoomExpandStackImage->Source = ZoomExpandStackImageEnabled->Source;
            break;

        case view::layout_id::grid: 
            ZoomLevelImage->Source = ZoomGridImage->Source;
            ZoomExpandStack->IsEnabled = false;
            ZoomExpandStackImage->Source = ZoomExpandStackImageDisabled->Source;
            break;
    }

    if (constants::general::stackState() == view::stack_state::expanded)
    {
        Windows::UI::Xaml::Automation::AutomationProperties::SetName(ZoomExpandStack,
            ref new String(L"Collapse stack"));
    }
    else
    {
        Windows::UI::Xaml::Automation::AutomationProperties::SetName(ZoomExpandStack,
            ref new String(L"Expand stack"));
    }
}

void page::updateCameraIcon()
{
    if (constants::general::zoomLevel() == view::layout_id::grid)
    {
        CameraImage->Source = CameraImageDisabled->Source;
        Camera->IsEnabled = false;
    }
    else
    {
        CameraImage->Source = CameraImageEnabled->Source;
        Camera->IsEnabled = true;
    }
}

void page::updateToolIcon()
{
    if (constants::general::zoomLevel() == view::layout_id::grid)
    {
        PenTypeImage->Source = PenTypeImageDisabled->Source;
        PenType->IsEnabled = false;
    }
    else
    {
        PenType->IsEnabled = true;
        view::command_id id = common::inkToolToCommandId(static_cast<int>(constants::ink::inkTool()));

        switch (id)
        {
            case view::command_id::tool_eraser: 
                PenTypeImage->Source = EraserImage->Source;
                _Color->IsEnabled = false;
                _Pen->IsEnabled = false;
                break;

            case view::command_id::tool_pen: 
                PenTypeImage->Source = BallpointPenImage->Source; 
                _Color->IsEnabled = true;
                _Pen->IsEnabled = true;
                break;
        }
    }
}

void page::updateColorIcon()
{
    this->Dispatcher->RunAsync(
        Windows::UI::Core::CoreDispatcherPriority::Normal,
        ref new Windows::UI::Core::DispatchedHandler(
                [this]()
                {
    if (constants::general::zoomLevel() == view::layout_id::grid)
    {
        _ColorImage->Source = _ColorImageDisabled->Source;
        _Color->IsEnabled = false;
    }
    else
    {
        _Color->IsEnabled = true;
        view::command_id id = common::colorToCommandId(constants::settings()->getInt((int)constants::ink::id::inkColor));

        switch (id)
        {
            case view::command_id::color_black: _ColorImage->Source = BlackColorImage->Source; break;
            case view::command_id::color_blue: _ColorImage->Source = BlueColorImage->Source; break;
            case view::command_id::color_pink: _ColorImage->Source = PinkColorImage->Source; break;
            case view::command_id::color_green: _ColorImage->Source = GreenColorImage->Source; break;
            case view::command_id::color_red: _ColorImage->Source = RedColorImage->Source; break;
            case view::command_id::color_yellow: _ColorImage->Source = YellowColorImage->Source; break;
        }
    }
                }, 
                Platform::CallbackContext::Any)
            );
}

void page::updateThicknessIcon()
{
    this->Dispatcher->RunAsync(
        Windows::UI::Core::CoreDispatcherPriority::Normal,
        ref new Windows::UI::Core::DispatchedHandler(
                [this]()
                {
                    if (constants::general::zoomLevel() == view::layout_id::grid)
                    {
                        _PenImage->Source = _PenImageDisabled->Source;
                        _Pen->IsEnabled = false;
                    }
                    else
                    {
                        _Pen->IsEnabled = true;
                        view::command_id id = common::widthToCommandId(constants::settings()->getFloat((int)constants::ink::id::baseWidth));

                        switch (id)
                        {
                            case view::command_id::pen_1: _PenImage->Source = Pen1Image->Source; break;
                            case view::command_id::pen_2: _PenImage->Source = Pen2Image->Source; break;
                            case view::command_id::pen_3: _PenImage->Source = Pen3Image->Source; break;
                            case view::command_id::pen_4: _PenImage->Source = Pen4Image->Source; break;
                            case view::command_id::pen_5: _PenImage->Source = Pen5Image->Source; break;
                        }
                    }
                }, 
                Platform::CallbackContext::Any)
            );
}

void page::updateTouchInputModeIcon()
{
    if (constants::ink::showTouchInputToggle())
    {
        if (constants::ink::touchInputMode())
        {
            TouchInputModeOff->Visibility = Windows::UI::Xaml::Visibility::Visible;
            TouchInputModeOn->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        }
        else
        {
            TouchInputModeOff->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
            TouchInputModeOn->Visibility = Windows::UI::Xaml::Visibility::Visible;
        }
    }
    else
    {
            TouchInputModeOff->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
            TouchInputModeOn->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
    }
    
    SettingsInputModeToggle->IsChecked = constants::ink::showTouchInputToggle();
}

void page::updatePaperTypeIcon()
{
    view::command_id id = common::paperTypeToCommandId(constants::settings()->getInt((int)constants::general::id::paperType));

    switch (id)
    {
        case view::command_id::paper_0: _PaperTypeImage->Source = Paper0Image->Source; break;
        case view::command_id::paper_1: _PaperTypeImage->Source = Paper1Image->Source; break;
        case view::command_id::paper_2: _PaperTypeImage->Source = Paper2Image->Source; break;
        case view::command_id::paper_3: _PaperTypeImage->Source = Paper3Image->Source; break;
        case view::command_id::paper_4: _PaperTypeImage->Source = Paper4Image->Source; break;
    }
}

void page::updateBackgroundColorSetting()
{
    g::packed_color c = constants::general::backgroundPackedColor();

    SettingsColorRed->Value = g::unpackColor_R(c);
    SettingsColorGreen->Value = g::unpackColor_G(c);
    SettingsColorBlue->Value = g::unpackColor_B(c);
}

void page::onAppBarClosed(Platform::Object^ sender, Platform::Object^ args)
{
    hideFlyouts();
    std::shared_ptr<ui_service> serviceImpl = std::dynamic_pointer_cast<ui_service>(_uiService);
    serviceImpl->raiseAppBarVisibilityChange(false);
}

/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached.  The Parameter
/// property is typically used to configure the page.</param>
void page::OnNavigatedTo(NavigationEventArgs^ e)
{
    (void) e;	// Unused parameter
}

void page::finishClick()
{
}

void page::showDialog(const wchar_t* message)
{
    String^ msg = ref new String(message);

    // we need to make sure XAML commands happen on the UI thread.
    this->Dispatcher->RunAsync(
        Windows::UI::Core::CoreDispatcherPriority::Normal,
        ref new Windows::UI::Core::DispatchedHandler(
                [this, msg]()
                {
                    DialogFlyout->IsOpen = true;
                    DialogGrid->Width = _TopCanvas->ActualWidth;
                    DialogMessage->Text = msg;
                }, 
                Platform::CallbackContext::Any)
            );
}

void page::nyi()
{
    this->showDialog(L"not yet implemented");
}

void page::enableAppBar(const bool enabled)
{
    _AppBar->Visibility = (enabled ? Windows::UI::Xaml::Visibility::Visible : Windows::UI::Xaml::Visibility::Collapsed);
}

void page::enableAppBarButton(const a::app_bar_button_id id, const bool enabled) 
{
    if (id == a::app_bar_button_id::copy_selection)
    {
        CopySelection->IsEnabled = enabled;
        CopySelectionImage->Source = (enabled ? CopySelectionImageEnabled->Source : CopySelectionImageDisabled->Source);
    }
    else if (id == a::app_bar_button_id::delete_page)
    {
        DeletePage->IsEnabled = enabled;
    }
    else if (id == a::app_bar_button_id::ok_page)
    {
        OKPage->IsEnabled = enabled;
    }
}

void page::hideAppBar()
{
    _AppBar->IsSticky = false;
    _AppBar->IsOpen = false;

    // default back to normal
    NormalLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Visible;
    NormalRightPanel->Visibility = Windows::UI::Xaml::Visibility::Visible;
    PhotoLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
    PhotoRightPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
    GridLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
    GridRightPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
    SelectionLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
    SelectionRightPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
}

void page::hideFlyouts()
{
    SettingsColorFlyout->IsOpen = false;
    ZoomFlyout->IsOpen = false;
    PenTypeFlyout->IsOpen = false;
    _ColorFlyout->IsOpen = false;
    CameraFlyout->IsOpen = false;
    _PenFlyout->IsOpen = false;
    PaperTypeFlyout->IsOpen = false;
}

void page::showAppBar(const a::app_bar_id id)
{
    hideFlyouts();

    if (id == a::app_bar_id::normal)
    {
        NormalLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Visible;
        NormalRightPanel->Visibility = Windows::UI::Xaml::Visibility::Visible;
        PhotoLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        PhotoRightPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        GridLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        GridRightPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        SelectionLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        SelectionRightPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        _AppBar->IsSticky = false;
    }
    else if (id == a::app_bar_id::none)
    {
        NormalLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        NormalRightPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        PhotoLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        PhotoRightPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        GridLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        GridRightPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        SelectionLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        SelectionRightPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        _AppBar->IsSticky = false;
    }
    else if (id == a::app_bar_id::photo)
    {
        NormalLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        NormalRightPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        PhotoLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Visible;
        PhotoRightPanel->Visibility = Windows::UI::Xaml::Visibility::Visible;
        GridLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        GridRightPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        SelectionLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        SelectionRightPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        _AppBar->IsSticky = true;
    }
    else if (id == a::app_bar_id::grid)
    {
        NormalLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        NormalRightPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        PhotoLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        PhotoRightPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        GridLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Visible;
        GridRightPanel->Visibility = Windows::UI::Xaml::Visibility::Visible;
        SelectionLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        SelectionRightPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        _AppBar->IsSticky = true;
    }
    else if (id == a::app_bar_id::lasso)
    {
        NormalLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        NormalRightPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        PhotoLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        PhotoRightPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        GridLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        GridRightPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
        SelectionLeftPanel->Visibility = Windows::UI::Xaml::Visibility::Visible;
        SelectionRightPanel->Visibility = Windows::UI::Xaml::Visibility::Visible;
        _AppBar->IsSticky = true;
    }

    if (id != a::app_bar_id::none)
    {
        _AppBar->IsOpen = true;
    }
}

/* ........................... touch input mode ........................... */
void page::clickTouchInputModeOn()
{
    hideFlyouts();

    bool handled = false;
    _commandObserver->onCommand(view::command_id::touch_mode_on, static_cast<void*>(&handled));
    finishClick();
}

void page::clickTouchInputModeOff()
{
    hideFlyouts();

    bool handled = false;
    _commandObserver->onCommand(view::command_id::touch_mode_off, static_cast<void*>(&handled));
    finishClick();
}

/* ........................... zoom levels ........................... */
void page::clickZoomLevel()
{
    hideFlyouts();
    ZoomFlyout->IsOpen = true;

    GeneralTransform^ gt = this->TransformToVisual(this->ZoomLevel);
    Point pt = gt->TransformPoint(Point(0, 0));

    Windows::UI::Xaml::Controls::Canvas::SetLeft(
        ZoomFlyout, 
        -pt.X);
    Windows::UI::Xaml::Controls::Canvas::SetTop(
        ZoomFlyout, 
        _TopCanvas->ActualHeight - 370 - _AppBar->ActualHeight);
}

void page::clickZoomGrid()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::zoom_grid, static_cast<void*>(&handled));
    finishClick();
}


void page::clickZoomFullPage()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::zoom_full_page, static_cast<void*>(&handled));
    finishClick();
}

void page::clickZoomFitToWidth()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::zoom_fit_to_width, static_cast<void*>(&handled));
    finishClick();
}

void page::clickZoomExpandStack()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::expand_stack, static_cast<void*>(&handled));
    finishClick();
}

/* ........................... pen types ........................... */
void page::clickPenType()
{
    hideFlyouts();
    PenTypeFlyout->IsOpen = true;

    GeneralTransform^ gt = this->TransformToVisual(this->PenType);
    Point pt = gt->TransformPoint(Point(0, 0));

    Windows::UI::Xaml::Controls::Canvas::SetLeft(
        PenTypeFlyout, 
        -pt.X);
    Windows::UI::Xaml::Controls::Canvas::SetTop(
        PenTypeFlyout, 
        _TopCanvas->ActualHeight - 290 - _AppBar->ActualHeight);
}

void page::clickBallpointPen()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::tool_pen, static_cast<void*>(&handled));
    finishClick();
}

void page::clickEraser()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::tool_eraser, static_cast<void*>(&handled));
    finishClick();
}

void page::clickSelectionTool()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::tool_selection, static_cast<void*>(&handled));
    finishClick();
}

/* ........................... pens ........................... */

void page::clickPen()
{
    hideFlyouts();
    _PenFlyout->IsOpen = true;

    GeneralTransform^ gt = this->TransformToVisual(this->_Pen);
    Point pt = gt->TransformPoint(Point(0, 0));

    Windows::UI::Xaml::Controls::Canvas::SetLeft(
        _PenFlyout, 
        -pt.X);
    Windows::UI::Xaml::Controls::Canvas::SetTop(
        _PenFlyout, 
        _TopCanvas->ActualHeight - 340 - _AppBar->ActualHeight);
}

void page::clickPen1()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::pen_1, static_cast<void*>(&handled));
    finishClick();
}

void page::clickPen2()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::pen_2, static_cast<void*>(&handled));
    finishClick();
}

void page::clickPen3()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::pen_3, static_cast<void*>(&handled));
    finishClick();
}

void page::clickPen4()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::pen_4, static_cast<void*>(&handled));
    finishClick();
}

void page::clickPen5()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::pen_5, static_cast<void*>(&handled));
    finishClick();
}

/* ........................... colors ........................... */

void page::clickColor()
{
    hideFlyouts();
    _ColorFlyout->IsOpen = true;

    GeneralTransform^ gt = this->TransformToVisual(this->_Color);
    Point pt = gt->TransformPoint(Point(0, 0));

    Windows::UI::Xaml::Controls::Canvas::SetLeft(
        _ColorFlyout, 
        -pt.X);
    Windows::UI::Xaml::Controls::Canvas::SetTop(
        _ColorFlyout, 
        _TopCanvas->ActualHeight - 404 - _AppBar->ActualHeight);
}

void page::clickBlackColor()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::color_black, static_cast<void*>(&handled));
    finishClick();
}

void page::clickRedColor()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::color_red, static_cast<void*>(&handled));
    finishClick();
}

void page::clickBlueColor()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::color_blue, static_cast<void*>(&handled));
    finishClick();
}

void page::clickYellowColor()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::color_yellow, static_cast<void*>(&handled));
    finishClick();
}

void page::clickGreenColor()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::color_green, static_cast<void*>(&handled));
    finishClick();
}

void page::clickPinkColor()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::color_pink, static_cast<void*>(&handled));
    finishClick();
}

/* ........................... photos ........................... */

void page::clickCamera()
{
    hideFlyouts();
    CameraFlyout->IsOpen = true;

    GeneralTransform^ gt = this->TransformToVisual(Camera);
    Point pt = gt->TransformPoint(Point(0, 0));

    Windows::UI::Xaml::Controls::Canvas::SetLeft(
        CameraFlyout, 
        -pt.X);
    Windows::UI::Xaml::Controls::Canvas::SetTop(
        CameraFlyout, 
        _TopCanvas->ActualHeight - 200 - _AppBar->ActualHeight);
}

void page::clickFileSystemPhoto()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::photo_filesystem, static_cast<void*>(&handled));
    finishClick();
}

void page::clickCameraPhoto()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::photo_camera, static_cast<void*>(&handled));
    finishClick();
}

/* ........................... paper types ........................... */
void page::clickPaperType()
{
    hideFlyouts();
    PaperTypeFlyout->IsOpen = true;

    GeneralTransform^ gt = this->TransformToVisual(this->PaperType);
    Point pt = gt->TransformPoint(Point(0, 0));

    Windows::UI::Xaml::Controls::Canvas::SetLeft(
        PaperTypeFlyout, 
        -pt.X);
    Windows::UI::Xaml::Controls::Canvas::SetTop(
        PaperTypeFlyout, 
        _TopCanvas->ActualHeight - 370 - _AppBar->ActualHeight);
}

void page::clickPaper0()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::paper_0, static_cast<void*>(&handled));
    finishClick();
}

void page::clickPaper1()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::paper_1, static_cast<void*>(&handled));
    finishClick();
}

void page::clickPaper2()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::paper_2, static_cast<void*>(&handled));
    finishClick();
}

void page::clickPaper3()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::paper_3, static_cast<void*>(&handled));
    finishClick();
}

void page::clickPaper4()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::paper_4, static_cast<void*>(&handled));
    finishClick();
}

/* ........................... other ........................... */

void page::clickCopy()
{
    hideFlyouts();
    bool handled = false;
    _commandObserver->onCommand(view::command_id::copy, static_cast<void*>(&handled));
    finishClick();
}

void page::clickPaste()
{
    hideFlyouts();
    bool handled = false;
    _commandObserver->onCommand(view::command_id::paste, static_cast<void*>(&handled));
    finishClick();
}

void page::clickAdd()
{
    hideFlyouts();
    bool handled = false;
    _commandObserver->onCommand(view::command_id::add_page, static_cast<void*>(&handled));
    finishClick();
}

void page::clickUndo()
{
    hideFlyouts();
    nyi();return;
    bool handled = false;
    _commandObserver->onCommand(view::command_id::undo, static_cast<void*>(&handled));
    finishClick();
}

void page::clickRedo()
{
    hideFlyouts();
    nyi();return;
    bool handled = false;
    _commandObserver->onCommand(view::command_id::redo, static_cast<void*>(&handled));
    finishClick();
}


/* ........................... photo app bar........................... */

void page::clickDeletePhoto()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::delete_photo, static_cast<void*>(&handled));
    finishClick();
}

void page::clickAlignPhoto()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::align_photo, static_cast<void*>(&handled));
    finishClick();
}

void page::clickBringToFrontPhoto()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::bring_to_front_photo, static_cast<void*>(&handled));
    finishClick();
}

void page::clickOKPhoto()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::ok_photo, static_cast<void*>(&handled));
    finishClick();
}

void page::clickCancelPhoto()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::cancel_photo, static_cast<void*>(&handled));
    finishClick();
}

/* ........................... grid app bar........................... */

void page::clickDeletePage()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::delete_page, static_cast<void*>(&handled));
    finishClick();
}

void page::clickOKPage()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::ok_page, static_cast<void*>(&handled));
    finishClick();
}

/* ........................... lasso app bar........................... */

void page::clickCopySelection()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::copy_selection, static_cast<void*>(&handled));
    finishClick();
}

void page::clickOKSelection()
{
    bool handled = false;
    _commandObserver->onCommand(view::command_id::ok_selection, static_cast<void*>(&handled));
    finishClick();
}

/* ........................... other ........................... */

void page::updateSettingsColor()
{
    int r = static_cast<int>(SettingsColorRed->Value);
    int g = static_cast<int>(SettingsColorGreen->Value);
    int b = static_cast<int>(SettingsColorBlue->Value);

    r = min(255, max(0, r));
    g = min(255, max(0, g));
    b = min(255, max(0, b));

    g::packed_color c = g::packColor(255, (b::uint8)r, (b::uint8)g, (b::uint8)b);
    constants::settings()->setInt((int)constants::general::id::backgroundPackedColor, static_cast<int>(c));
}

void page::settingsInputModeChecked()
{
    bool isChecked = SettingsInputModeToggle->IsChecked->Value;
    constants::settings()->setBool((int)constants::ink::id::showTouchInputToggle, isChecked);
    this->updateTouchInputModeIcon();
}

void page::onCommandsRequested(
    Windows::UI::ApplicationSettings::SettingsPane^ settingsPane, 
    Windows::UI::ApplicationSettings::SettingsPaneCommandsRequestedEventArgs^ eventArgs
    )
{
    UICommandInvokedHandler^ handler = ref new UICommandInvokedHandler(this, &page::onSettingsCommand);

    SettingsCommand^ generalCommand = ref new SettingsCommand("generalSettings", "General", handler);
    eventArgs->Request->ApplicationCommands->Append(generalCommand);

    SettingsCommand^ aboutCommand = ref new SettingsCommand("aboutPage", "About", handler);
    eventArgs->Request->ApplicationCommands->Append(aboutCommand);
}

void page::onSettingsCommand(IUICommand^ command)
{
    SettingsCommand^ settingsCommand = safe_cast<SettingsCommand^>(command);

    if (settingsCommand->Label == "General")
    {
        this->hideFlyouts();
        SettingsColorFlyout->IsOpen = true;
        SettingsColorDialogGrid->Height = _TopCanvas->ActualHeight;
        SettingsColorFlyout->SetValue(_TopCanvas->LeftProperty, _TopCanvas->ActualWidth - 300);
    }
    else if (settingsCommand->Label == "About")
    {
        this->hideFlyouts();
        SettingsAboutFlyout->IsOpen = true;
        SettingsAboutDialogGrid->Height = _TopCanvas->ActualHeight;
        SettingsAboutFlyout->SetValue(_TopCanvas->LeftProperty, _TopCanvas->ActualWidth - 300);
    }
}
